package com.zwj.se.collection;

import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;

/**
 * 将能抽象出来的方法，实现，其他的让子类去实现
 *
 * @author 张文接
 * @version 1.0
 * @createTime 2024/8/26 10:43
 */
public abstract class AbsCollection<E> implements Collection<E> {
    /**
     * 外部无法创建抽象实例
     */
    protected AbsCollection() {
    }

    //集合最大容量
    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

    public abstract Iterator<E> iterator();

    public abstract int size();

    public boolean isEmpty() {
        return size() == 0;
    }

    /**
     * 当前集合是否包含元素 o
     *
     * @param o 要测试集合中是否存在的元素
     * @return 是否包含
     */
    public boolean contains(Object o) {
        Iterator<E> iterator = iterator();
        if (o == null) {
            while (iterator.hasNext()) {
                if (iterator.next() == null) {
                    return true;
                }
            }
        } else {
            while (iterator.hasNext()) {
                if (iterator.next().equals(o)) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * 将当前集合转换成数组，如果在转换的过程中，集合发生了变化，则数组用null或者0 填充
     *
     * @return 数组
     */
    @Override
    public Object[] toArray() {
        //创建一个容量与当前集合一样的数组
        Object[] r = new Object[size()];
        Iterator<E> it = iterator();
        //循环遍历
        for (int i = 0; i < r.length; i++) {
            //若当前集合的元素减少了
            if (!it.hasNext()) {
                //则重新创建一个数组，将集合的元素放进去，不会造成数组内存的浪费
                return Arrays.copyOf(r, i);
            }
            //将集合的索引位置为i的数据赋值给集合索引位置为i
            r[i] = it.next();
        }
        //若当前集合的元素增加了，则进行数组扩容，每次长度扩大2倍
        return it.hasNext() ? finishToArray(r, it) : r;
    }

    /**
     * @param r   初始数组
     * @param it  集合的迭代器
     * @param <T> 泛型
     * @return 扩容后的数组
     */
    private static <T> T[] finishToArray(T[] r, Iterator<?> it) {
        //初始数组的长度
        int i = r.length;
        while (it.hasNext()) {
            int cap = r.length;
            //判断初始数组有没有被填满，若满了，则新创建一个数组扩容，扩容规则为 n -> n + (n / 2 + 1) = 1.5n + 1，即扩容为原本的1.5倍 + 1
            if (i == cap) {
                int newCap = cap + (cap >> 1) + 1;
                //判断扩容后的容量是否超过Integer类型的（最大值 - 8）
                if (newCap - MAX_ARRAY_SIZE > 0) {
                    //若超过
                    newCap = hugeCapacity(cap + 1);
                }
                r = Arrays.copyOf(r, newCap);
            }
            r[i++] = (T) it.next();
        }
        return (i == r.length) ? r : Arrays.copyOf(r, i);
    }

    /**
     * 容量检查
     *
     * @param minCapacity 最小容量
     * @return 容量
     */
    private static int hugeCapacity(int minCapacity) {
        //异常处理
        if (minCapacity < 0) {
            throw new OutOfMemoryError("Required array size too large");
        }
        //若 minCapacity >（Integer.MAX_VALUE - 8）则，返回Integer的最大值 （Integer.MAX_VALUE），否则相应 （Integer.MAX_VALUE - 8）
        return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE;
    }

    @SuppressWarnings("unchecked")
    public <T> T[] toArray(T[] a) {
        int size = size();
        //判断数组a与迭代器的元素的大小，取值大的那一个数组
        T[] r = a.length >= size ? a :
                (T[]) Array.newInstance(a.getClass().getComponentType(), size);
        Iterator<E> it = iterator();
        for (int i = 0; i < r.length; i++) {
            //元素比预期少,数组a后续位置用null填充
            if (!it.hasNext()){
                //TODO
                //响应已完成copy的数组
                return a;
            }
            //根据顺序赋值
            r[i] = (T) it.next();
        }

        return a;
    }
}
